﻿// -----------------------------------------------------------------------
// <copyright file="MailNotificationEngine.cs" company="EPAM Systems">
////Copyright (c) EPAM Systems, 2012. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

namespace MBOP.Notification.Services
{
	#region Usings

	using System;
	using System.Collections.Generic;
	using System.Net.Mail;
	using System.Threading.Tasks;

	using MBOP.Configuration.ConfigElements;
	using MBOP.Core.DTO;
	using MBOP.Core.Entities.Common;
	using MBOP.Core.Entities.Notification;
	using MBOP.Core.Interfaces.Notification;
	using MBOP.Core.Interfaces.Services;
	using MBOP.Core.Interfaces.TextTemplatesCore;
	using MBOP.Helpers.ExceptionHandling.ExceptionHandlers;

	#endregion

	/// <summary>
	/// Provides the mail notification engine.
	/// </summary>
	public class MailNotificationEngine : INotificationEngine
	{
		#region Constants

		/// <summary>
		/// Represents the receiver email parameter name.
		/// </summary>
		private const string PARAMETER_TO = "to";

		/// <summary>
		/// Represents the subject of the message parameter name.
		/// </summary>
		private const string PARAMETER_SUBJECT = "subject";

		/// <summary>
		/// Represents the body of the message parameter name.
		/// </summary>
		private const string PARAMETER_CONTENT = "content";

		/// <summary>
		/// Represents the email addresses separator.
		/// </summary>
		private const char EMAIL_SEPARATOR = ',';

		#endregion

		#region Private Fields

		/// <summary>
		/// Represents the template resolver.
		/// </summary>
		private ITemplateResolver _templateResolver;

		/// <summary>
		/// Represents the person information service.
		/// </summary>
		private IPersonInformationService _personInfoService;

		/// <summary>
		/// Represents the email engine config element.
		/// </summary>
		private EmailServiceElement _configElement;

		#endregion

		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="MailNotificationEngine"/> class.
		/// </summary>
		/// <param name="templateResolver">The <see cref="ITemplateResolver"/> implementer.</param>
		/// <param name="personInfoService">The <see cref="IPersonInformationService"/> implementer.</param>
		/// <param name="configElement">The mail notification engine configuration element.</param>
		public MailNotificationEngine(ITemplateResolver templateResolver, IPersonInformationService personInfoService, EmailServiceElement configElement)
		{
			this._templateResolver = templateResolver;
			this._personInfoService = personInfoService;
			this._configElement = configElement;
		}

		#endregion

		#region INotificationEngine Implementation

		#region Methods

		/// <summary>
		/// Notifies receivers that the current event wired up
		/// </summary>
		/// <param name="template">The event template.</param>
		/// <param name="receiversIdentityCollection">Collection of the receivers identities.</param>
		/// <param name="eventData">The data of the event</param>
		public void Notify(NotificationTemplate template, IDictionary<string, PersonFindingType> receiversIdentityCollection, dynamic eventData)
		{
			if (template.Type == NotificationTypes.Email && this.IsCorrectTemplate(template))
			{
				Task.Factory.StartNew(
					() =>
					{
						using (SmtpClient smtpClient = new SmtpClient(_configElement.SmtpHost, _configElement.Port))
						{
							smtpClient.UseDefaultCredentials = true;

							IEnumerable<MailMessage> messages = CreateMessageCollectionFromTemplate(template, receiversIdentityCollection, eventData);

							try
							{
								foreach (var message in messages)
								{
									smtpClient.Send(message);

									message.Dispose();
								}
							}
							catch (Exception ex)
							{
								BusinessLogicExceptionHandler.HandleException(ex);
							}
						}
					});
			}
		}

		#endregion

		#endregion

		#region Private Methods

		/// <summary>
		/// Creates email messages collection.
		/// </summary>
		/// <param name="template">The event template.</param>
		/// <param name="receiversIdentityCollection">Collection of the receivers identities.</param>
		/// <param name="eventData">The data of the event.</param>
		/// <returns>Collection of messages.</returns>
		private IEnumerable<MailMessage> CreateMessageCollectionFromTemplate(NotificationTemplate template, IDictionary<string, PersonFindingType> receiversIdentityCollection, dynamic eventData)
		{
			List<MailMessage> messages = new List<MailMessage>();

			foreach (var personElement in receiversIdentityCollection)
			{
				PersonInfo personInfo = this._personInfoService.GetPersonInfo(personElement.Key, personElement.Value, false);

				MailMessage message = new MailMessage();

				message.Priority = MailPriority.Normal;

				message.From = new MailAddress(this._configElement.SenderEmail, this._configElement.SenderDisplayingName);

				var templateData = new { UserInfo = personInfo, EventData = eventData };

				string targetEmail = this._templateResolver.ResolveTemplate(template.Parameters[PARAMETER_TO], templateData);

				message.To.Add(targetEmail);

				message.Subject = this._templateResolver.ResolveTemplate(template.Parameters[PARAMETER_SUBJECT], templateData);

				message.Body = this._templateResolver.ResolveTemplate(template.Parameters[PARAMETER_CONTENT], templateData);

				message.IsBodyHtml = true;

				messages.Add(message);
			}

			return messages;
		}

		/// <summary>
		/// Checks that the current template is correct or not.
		/// </summary>
		/// <param name="template">The current template.</param>
		/// <returns>The result of the checking.</returns>
		private bool IsCorrectTemplate(NotificationTemplate template)
		{
			return template.Parameters[PARAMETER_TO] != null
				&& template.Parameters[PARAMETER_SUBJECT] != null
				&& template.Parameters[PARAMETER_CONTENT] != null;
		}

		#endregion
	}
}
